#include <dspSimulator/instruction/spkernel.h>


bool SPKERNEL::checkCondition(std::shared_ptr<DspMachine> dspMachine) {
    return true;
}

void SPKERNEL::loadInstIRIntoJit(llvm::LLVMContext *llvmContext, llvm::Module *module,
                                 std::shared_ptr<llvm::IRBuilder<>> irBuilder) {

}

std::shared_ptr<Instruction> SPKERNEL::decode(std::shared_ptr<InstInfo> instInfo, u64 baseCycle) {
    std::shared_ptr<SPKERNEL> spkernel;
    auto dspInstInfo = std::dynamic_pointer_cast<DspInstInfo>(instInfo);
    bool isStandardInst = dspInstInfo->isStandardInstruction();
    if (isStandardInst) {
        auto data = vectorToBitSet<32>(dspInstInfo->getBits());
        if (checkBits<4>(data, 28, 0b0) && checkBits<20>(data, 2, 0b00001101000000000000)) {
            spkernel = std::make_shared<SPKERNEL>(dspInstInfo->getAddress(), baseCycle);
            spkernel->fstg = spkernel->fcyc = extractBits<6>(data, 22).to_ulong();
            spkernel->s = data[1];
            spkernel->p = data[0];
            spkernel->instFormat = InstFormat::Kind1;
        }
    } else {
        auto data = vectorToBitSet<16>(dspInstInfo->getBits());
        if (checkBits<4>(data, 10, 0b0111) && checkBits<6>(data, 1, 0b110011)) {
            spkernel = std::make_shared<SPKERNEL>(dspInstInfo->getAddress(), baseCycle);
            spkernel->isCompactInstruction = true;
            spkernel->compactInstKind = "Uspk";
            spkernel->fstg = data[0];
            spkernel->fstg += extractBits<1>(data, 15).to_ulong() << 1;
            spkernel->fstg += extractBits<1>(data, 14).to_ulong() << 2;
            spkernel->fstg += extractBits<1>(data, 9).to_ulong() << 3;
            spkernel->fstg += extractBits<1>(data, 8).to_ulong() << 4;
            spkernel->fstg += extractBits<1>(data, 7).to_ulong() << 5;
            spkernel->PROT = dspInstInfo->getPROT();
            spkernel->RS = dspInstInfo->getRS();
            spkernel->SAT = dspInstInfo->getSAT();
            spkernel->DSZ = dspInstInfo->getDSZ();
            spkernel->RS = dspInstInfo->getRS();
            spkernel->p = dspInstInfo->getP();
            spkernel->fixUpRegOnCompactInstruction();
            spkernel->instFormat = InstFormat::Kind1;
        }
    }
    return spkernel;
}

void SPKERNEL::executeCustom(std::shared_ptr<TargetMachine> targetMachine, ExecutePhase executePhase) {

}

std::shared_ptr<DspInstruction> SPKERNEL::clone() {
    return std::make_shared<SPKERNEL>(*this);
}

std::string SPKERNEL::toString() const {
    std::string res = m_name + " ";
    res += std::to_string(fstg) + "," + std::to_string(fcyc);
    return res;
}
